package com.zeyu.framework.core.service;

import com.zeyu.framework.core.persistence.dao.TreeDao;
import com.zeyu.framework.core.persistence.entity.TreeEntity;
import com.zeyu.framework.utils.Reflections;
import com.zeyu.framework.utils.StringUtils;

import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Service基类
 */
@Transactional(readOnly = true)
public abstract class TreeService<D extends TreeDao<T>, T extends TreeEntity<T>> extends CrudService<D, T> {

    // ================================================================
    // Constants
    // ================================================================

    // ================================================================
    // Fields
    // ================================================================

    // ================================================================
    // Constructors
    // ================================================================

    // ================================================================
    // Methods from/for super Interfaces or SuperClass
    // ================================================================

    // ================================================================
    // Public or Protected Methods
    // ================================================================

    @Transactional
    @SuppressWarnings("unchecked")
    @Override
    public void save(T entity) {

        Class<?> entityClass = Reflections.getClassGenricType(getClass(), 1);

        // 如果没有设置父节点，则代表为跟节点，有则获取父节点实体
        if (entity.getParent() == null || StringUtils.isBlank(entity.getParentId()) || "0".equals(entity.getParentId())) {
            entity.setParent(null);
        } else {
            entity.setParent(super.get(entity.getParentId()));
        }
        if (entity.getParent() == null) {
            T parentEntity;
            try {
                parentEntity = (T) entityClass.getConstructor(String.class).newInstance("0");
            } catch (Exception e) {
                throw new ServiceException(e);
            }
            entity.setParent(parentEntity);
            entity.getParent().setParentIds(StringUtils.EMPTY);
        }

        // 获取修改前的parentIds，用于更新子节点的parentIds
        String oldParentIds = entity.getParentIds();

        // 设置新的父节点串
        entity.setParentIds(entity.getParent().getParentIds() + entity.getParent().getId() + ",");

        // 保存或更新实体
        super.save(entity);

        // 更新子节点 parentIds
        T o;
        try {
            o = (T) entityClass.newInstance();
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        o.setParentIds("%," + entity.getId() + ",%");
        List<T> list = dao.findByParentIdsLike(o);
        list.stream().filter(e -> e.getParentIds() != null && oldParentIds != null).forEach(e -> {
            e.setParentIds(e.getParentIds().replace(oldParentIds, entity.getParentIds()));
            preUpdateChild(entity, e);
            dao.updateParentIds(e);
        });

    }

    /**
     * 预留接口，用户更新子节前调用
     *
     * @param childEntity 子实体
     */
    @Transactional
    protected void preUpdateChild(T entity, T childEntity) {
        logger.debug("entity is {}", entity);
        logger.debug("childEntity is {}", childEntity);
    }

    // ================================================================
    // Getter & Setter
    // ================================================================

    // ================================================================
    // Private Methods
    // ================================================================

    // ================================================================
    // Inner or Anonymous Class
    // ================================================================

    // ================================================================
    // Test Methods
    // ================================================================
}
